package org.lc.gateway.handler;

import java.nio.charset.StandardCharsets;

import org.apache.http.HttpHeaders;
import org.lc.gateway.execption.CustomAuthException;
import org.lc.platform.base.enums.AuthResultEnum;
import org.lc.platform.base.result.Result;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.server.resource.InvalidBearerTokenException;
import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import cn.hutool.json.JSONUtil;
import reactor.core.publisher.Mono;

/**
 * 无效token/token过期 自定义响应
 *
 * @author lc
 */
@Component
public class AuthServerAuthenticationEntryPoint implements ServerAuthenticationEntryPoint {

    @Override
    public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException e) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.OK);
        response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
        response.getHeaders().set("Access-Control-Allow-Origin", "*");
        response.getHeaders().set("Cache-Control", "no-cache");
        var noToken = AuthResultEnum.INVALID_TOKEN;
        Result<?> result = Result.error(noToken.getCode(), e.getMessage());
        if (e instanceof CustomAuthException) {
            result.setMsg(((CustomAuthException) e).getMsg());
            result.setCode(((CustomAuthException) e).getCode());
        }
        if (e instanceof InvalidBearerTokenException) {
            result.setMsg(noToken.getMsg());
        }
        String body = JSONUtil.toJsonStr(result);
        DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(StandardCharsets.UTF_8));
        return response.writeWith(Mono.just(buffer)).doFinally(s -> {
            DataBufferUtils.release(buffer);
        });
    }
}

